import { ref, DirectiveBinding, createApp, h, watch } from 'vue';
import Button from '@/components/Button/index.vue'; // 确保路径正确
import 'vant/lib/index.css';
import { Button as VanButton, Overlay } from 'vant';
import { debounce, throttle } from "@/utils/index";

interface BtnObj {
    style?: any;
    class?: any;
    value?: string;
    round?: boolean;
}

interface Props {
    defaultStyle?: any;
    defaultCircle?: boolean;
    dynamicSlotName?: string[];
    type?: 'above' | 'below';
    btnObj?: BtnObj;
    isReplace?: boolean;
}

/**
 * 扩展的HTMLElement接口，包含指令所需的附加属性
 */
interface ElType extends HTMLElement {
    _onResize?: () => void;
    _index?: number;
}

const defaultBtnObj = (): BtnObj => ({
    style: {
        width: '48px',
        height: '48px',
        lineHeight: '50px',
        display: 'inline-block',
        border: 'none',
        textAlign: 'center',
        position: 'relative',
    },
    class: '',
    value: undefined,
    round: true,
});

const calculatePositionFactor = (screenWidth: number) => {
    const x0 = 375;
    const x1 = 1536;
    const y0 = 2.8;
    const y1 = 5;

    return y0 + ((y1 - y0) / (x1 - x0)) * (screenWidth - x0);
};

const width = ref(calculatePositionFactor(window.innerWidth));

const defaultProps: Props = {
    defaultStyle: {
        position: 'absolute',
        left: '50%',
        transform: 'translate(-50%, 250%)',
    },
    defaultCircle: true,
    dynamicSlotName: ['item1', 'item2'],
    type: 'above',
    btnObj: defaultBtnObj(),
};

const isMobileDevice = () => window.innerWidth <= 768;

const createButtonApp = (props: any, onClick: (event: MouseEvent) => void) => {
    const app = createApp({
        render() {
            return h(Button, { ...props, onClick });
        }
    });
    app.use(VanButton);
    return app;
};

const closeOverlay = ref(false);
const onOverlayClick = () => {
    closeOverlay.value = true;
};
// 创建 Overlay 单例
let overlayInstance: any;
let overlayContent = ref({});
let clipPath = ref('');
let watchOverlay: () => void;

const createOverlay = () => {
    if (!overlayInstance) {
        const overlayEl = document.createElement('div');
        const overlayApp = createApp({
            data() {
                return { showOverlay: false };
            },
            render() {
                return h(Overlay, {
                    show: this.showOverlay,
                    style: overlayContent.value,
                    onClick: () => {
                        this.showOverlay = false;
                        onOverlayClick();
                    }
                });
            }
        });

        overlayApp.mount(overlayEl);
        document.body.appendChild(overlayEl);
        overlayInstance = overlayApp._instance;
    }
    return overlayInstance;
};

const createMenuPosition = (type: Props['type']) => {
    // 增加对PC端菜单显示位置的调整
    if (type === 'above') {
        return isMobileDevice()
            ? { position: 'absolute', left: '50%', bottom: '100%' }
            : { position: 'absolute', left: '50%', bottom: 'calc(100% + 10px)' };
    } else {
        return isMobileDevice()
            ? { position: 'absolute', left: '50%', top: '250%' }
            : { position: 'absolute', left: '50%', top: 'calc(100% + 10px)' };
    }
};

const createComputedPosition = (index: number, total: number, interval: number, isReplace?: boolean) => {
    const angle = total > 1 ? (180 / (total + 1)) * (index + 1) : 0;
    const radians = (angle * Math.PI) / 180;
    const x = interval / (isMobileDevice() ? 1 : 1.5) * Math.cos(radians);
    const y = interval / (isMobileDevice() ? 1 : 1.75) * Math.sin(radians);
    return {
        position: 'absolute',
        left: `${x - interval / width.value}px`,
        top: `${-y}px`,
        transition: 'left 0.2s, top 0.2s',
    };
};

const adjustIntervalForDevice = () => {
    return isMobileDevice() ? 64 : 96; // 移动端间隔64px，桌面端间隔96px
};

const renderButton = (props: any, onClick: (event: MouseEvent) => void) => {
    const buttonEl = document.createElement('div');
    const buttonApp = createButtonApp(props, onClick);
    buttonApp.mount(buttonEl);
    return buttonEl;
};
let dynamicSlotName: number | undefined;
const renderMenuItems = (el: HTMLElement, props: Props, handleButtonClick: (item: string, event: MouseEvent) => void, menuVisible: boolean) => {
    let menu: HTMLElement = el.querySelector('.oy-menu')!;
    if (!menu) {
        menu = document.createElement('div');
        menu.className = 'oy-menu';

        menu.style.display = menuVisible ? 'block' : 'none';
        Object.assign(menu.style, createMenuPosition(props.type as 'above' | 'below'));
        el.appendChild(menu);
    }

    let interval = adjustIntervalForDevice();
    dynamicSlotName = props.dynamicSlotName?.length;
    props.dynamicSlotName?.forEach((item: any, index: any) => {
        let menuItem: HTMLElement = menu.querySelector(`.oy-menu-item[data-index="${index}"]`)!;
        if (!menuItem) {
            menuItem = document.createElement('div');
            menuItem.className = 'oy-menu-item';
            menuItem.setAttribute('data-index', index.toString());
            Object.assign(menuItem.style, createComputedPosition(index, props.dynamicSlotName!.length, interval, props.isReplace));

            const buttonEl = renderButton({ round: true, value: item }, (e: MouseEvent) => handleButtonClick(item, e));
            menuItem.appendChild(buttonEl);

            menu.appendChild(menuItem);
        } else {
            Object.assign(menuItem.style, createComputedPosition(index, props.dynamicSlotName!.length, interval, props.isReplace));
        }
    });
};
let currentEl: HTMLElement;
const createClipPath = (el: HTMLElement) => {
    if (currentEl !== el && currentEl) return;
    const rect = el.getBoundingClientRect();
    let interval = adjustIntervalForDevice();
    const { top } = createComputedPosition(dynamicSlotName! / 2, dynamicSlotName!, interval, false);
    const halfSize = (isMobileDevice() ? 1.5 : 1.5) * Math.abs(parseInt(top.split("px")[0]));
    const x = rect.left + rect.width / 2;
    const y = rect.top + rect.height / 2;
    // const rectSize = isMobileDevice() ? 150 : 250;
    // const halfSize = rectSize / 2;
    clipPath.value = `
      polygon(
          0 0, 
          0 100%, 
          100% 100%, 
          100% 0, 
          50% 0, 
          50% ${y - halfSize}px,
          ${x + halfSize}px ${y - halfSize}px,
          ${x + halfSize}px ${y + halfSize}px,
          ${x - halfSize}px ${y + halfSize}px,
          ${x - halfSize}px ${y - halfSize}px,
          50% ${y - halfSize}px,
          50% 0
      )
  `;
}

watch(clipPath, (newClipPath) => {
    overlayContent.value = { clipPath: newClipPath };
});

export const menuDirective = {
    beforeMount(el: ElType, binding: DirectiveBinding) {
        const props = { ...defaultProps, ...binding.value };

        // 初始状态由父组件传入控制
        let menuVisible = binding.value.show;

        const handleButtonClick = (item: string, event: MouseEvent) => {
            // event.stopPropagation(); // 阻止事件冒泡
            if (binding.value?.onBtnClick) {
                binding.value.onBtnClick(item, event);
            }
        };

        createOverlay();
        if (props.isReplace) {
            // Replace the element with the button
            const buttonProps = { ...props.btnObj, onClick: (e: MouseEvent) => handleButtonClick(props.btnObj?.value || '', e) };
            const buttonEl = renderButton(buttonProps, (e: MouseEvent) => handleButtonClick(props.btnObj?.value || '', e));
            el.innerHTML = ''; // 清空原有内容
            el.appendChild(buttonEl.firstChild as Node); // 插入按钮元素

            renderMenuItems(el, props, handleButtonClick, menuVisible);
        } else {
            renderMenuItems(el, props, handleButtonClick, menuVisible);
        }

        // 监听窗口大小变化，动态调整间隔
        const onResize = () => {
            width.value = calculatePositionFactor(window.innerWidth);
            renderMenuItems(el, props, handleButtonClick, menuVisible); // 只更新样式，不重新创建元素
            createClipPath(el)
        }

        window.addEventListener('resize', onResize);

        // 在指令卸载时移除监听器
        el._onResize = onResize;
        el._index = binding.value.index; // 保存当前的 index
    },
    updated(el: HTMLElement, binding: DirectiveBinding) {
        if (binding.oldValue && binding.value.show === binding.oldValue.show) {
            return; // 如果 show 值没有变化，则不执行后续操作
        }
        currentEl = el;
        createClipPath(el)
        const shouldShow = binding.value.show;
        if (overlayInstance) {
            overlayInstance.data.showOverlay = shouldShow;
        }

        const menu: HTMLElement = el.querySelector('.oy-menu')!;
        if (menu) {
            menu.style.display = shouldShow ? 'block' : 'none';
        }

        // 解除之前的 watch
        if (watchOverlay) {
            watchOverlay();
        }

        // 重新设置 watch
        watchOverlay = watch(closeOverlay, (n, o) => {
            if (n) {
                binding.value.onCloseOverlay(binding.value.index);
                closeOverlay.value = false;
            }
        });
    },
    unmounted(el: ElType) {
        window.removeEventListener('resize', el._onResize!);
        el.innerHTML = '';
        if (watchOverlay) {
            watchOverlay();
        }
    },
};